package com.xgy.userauthsystem.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
import java.util.Base64;
import java.io.ByteArrayOutputStream;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import java.io.IOException;

/**
 * 验证码服务类
 * 生成和验证图形验证码
 */
@Service
public class CaptchaService {
    
    private static final Logger logger = LoggerFactory.getLogger(CaptchaService.class);

    private final StringRedisTemplate redisTemplate;// Redis模板，用于操作字符串类型的键值对
    
    // 图形验证码缓存前缀和有效期（分钟）
    private static final String CAPTCHA_PREFIX = "captcha:";// 验证码缓存前缀
    private static final long CAPTCHA_EXPIRE_MINUTES = 5;// 验证码有效期（分钟）
    
    private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";// 验证码字符集
    private static final int CAPTCHA_LENGTH = 4;// 验证码长度

    // 构造函数，注入Redis模板
    @Autowired
    public CaptchaService(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 生成验证码图片和文本
     *
     * @param captchaId 验证码标识符
     * @return 包含验证码图片Base64编码和文本的数组
     */
    public String[] generateCaptcha(String captchaId) {
        String captchaText = generateRandomText();// 生成随机验证码文本
        String captchaImage = generateCaptchaImage(captchaText);// 生成验证码图片
        
        // 存储验证码文本到Redis，关联captchaId
        String key = CAPTCHA_PREFIX + captchaId;// 验证码缓存键
        redisTemplate.opsForValue().set(key, captchaText, CAPTCHA_EXPIRE_MINUTES, TimeUnit.MINUTES);// 存储验证码文本到Redis，设置有效期（分钟）
        
        return new String[]{captchaImage, captchaText};
    }

    /**
     * 验证验证码
     *
     * @param captchaId 验证码标识符
     * @param userInput 用户输入的验证码
     * @return 验证是否通过
     */
    public boolean validateCaptcha(String captchaId, String userInput) {
        if (captchaId == null || userInput == null) {
            return false;
        }
        
        String key = CAPTCHA_PREFIX + captchaId;
        String storedCaptcha = redisTemplate.opsForValue().get(key);
        if (storedCaptcha == null) {
            return false;
        }
        
        // 不区分大小写比较
        boolean isValid = storedCaptcha.equalsIgnoreCase(userInput);
        
        // 验证后删除验证码（一次性使用）
        if (isValid) {
            redisTemplate.delete(key);
        }
        
        return isValid;
    }

    /**
     * 生成随机验证码文本
     * @return 随机验证码文本
     */
    private String generateRandomText() {
        Random random = new Random();// 随机数生成器
        StringBuilder sb = new StringBuilder(CAPTCHA_LENGTH);
        for (int i = 0; i < CAPTCHA_LENGTH; i++) {
            sb.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length())));
        }
        return sb.toString();
    }

    /**
     * 生成验证码图片
     * @param captchaText 验证码文本
     * @return 图片的Base64编码
     */
    private String generateCaptchaImage(String captchaText) {
        int width = 120;
        int height = 40;
        
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = image.createGraphics();
        
        // 设置抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        
        // 绘制背景
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, width, height);
        
        // 添加干扰线
        Random random = new Random();
        g2d.setColor(Color.LIGHT_GRAY);
        for (int i = 0; i < 5; i++) {
            int x1 = random.nextInt(width);
            int y1 = random.nextInt(height);
            int x2 = random.nextInt(width);
            int y2 = random.nextInt(height);
            g2d.drawLine(x1, y1, x2, y2);
        }
        
        // 绘制验证码文本
        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("Arial", Font.BOLD, 20));
        
        // 计算文本位置
        FontMetrics fm = g2d.getFontMetrics();
        int textWidth = fm.stringWidth(captchaText);
        int x = (width - textWidth) / 2;
        int y = (height - fm.getHeight()) / 2 + fm.getAscent();
        
        // 绘制每个字符（带随机旋转）
        for (int i = 0; i < captchaText.length(); i++) {
            String ch = String.valueOf(captchaText.charAt(i));
            int charX = x + i * (textWidth / captchaText.length());
            
            // 随机旋转角度
            double angle = (random.nextDouble() - 0.5) * 0.5;
            g2d.rotate(angle, charX + fm.charWidth(captchaText.charAt(i)) / 2.0, y);
            g2d.drawString(ch, charX, y);
            g2d.rotate(-angle, charX + fm.charWidth(captchaText.charAt(i)) / 2.0, y);
        }
        
        g2d.dispose();
        
        // 转换为Base64
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "png", baos);
            byte[] imageBytes = baos.toByteArray();
            return Base64.getEncoder().encodeToString(imageBytes);
        } catch (IOException e) {
            logger.error("生成验证码图片时发生错误", e);
            return "";
        }
    }
}